package com.example.teacher.activity;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;

import com.example.teacher.SignalingClient2;
import com.example.teacher.adpter.PeerConnectionAdapter;
import com.example.teacher.R;
import com.example.teacher.adpter.SdpAdapter;
import com.example.teacher.SignalingClient;
import com.orhanobut.hawk.Hawk;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;

import org.json.JSONObject;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.Camera1Enumerator;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class MainActivity extends RxAppCompatActivity implements SignalingClient.Callback {


    EglBase.Context eglBaseContext;
    PeerConnectionFactory peerConnectionFactory;
    SurfaceViewRenderer localView;
    MediaStream mediaStream;
    List<PeerConnection.IceServer> iceServers;

    public HashMap<String, PeerConnection> peerConnectionMap;
    SurfaceViewRenderer[] remoteViews;
    int remoteViewsIndex = 0;
    private String room = "OldPlace";
    final int ALL_PERMISSIONS_CODE = 1;
    private static  String TAG="SignalingClient2222";
    private AudioManager audioManager;
    private  AudioSource audioSource;
    private  AudioTrack localAudioTrack;
    private  MediaConstraints audioConstraints;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(this, Manifest.permission.MODIFY_AUDIO_SETTINGS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO,Manifest.permission.MODIFY_AUDIO_SETTINGS}, ALL_PERMISSIONS_CODE);
        } else {
            // all permissions already granted
            start();
        }
       // OpenSpeaker();
    }
    @SuppressLint({"NewApi", "WrongConstant"})
    public void OpenSpeaker() {
        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        try {
            audioManager.setMode(AudioManager.ROUTE_SPEAKER);
            // 获取当前通话音量
            if (!audioManager.isSpeakerphoneOn()) {
                audioManager.setSpeakerphoneOn(true);
                audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
                        audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
                        AudioManager.STREAM_VOICE_CALL);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Log.d("audioManager",audioManager.isMicrophoneMute()+"")
        ;
    }
    private void start(){
        //tun:125.88.151.100:3479"s
        peerConnectionMap = new HashMap<>();
        iceServers = new ArrayList<>();

        iceServers.add(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer());
        eglBaseContext = EglBase.create().getEglBaseContext();

        // create PeerConnectionFactory
        PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions
                .builder(this)
                .createInitializationOptions());
        PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
        DefaultVideoEncoderFactory defaultVideoEncoderFactory =
                new DefaultVideoEncoderFactory(eglBaseContext, true, true);
        DefaultVideoDecoderFactory defaultVideoDecoderFactory =
                new DefaultVideoDecoderFactory(eglBaseContext);
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setOptions(options)
                .setVideoEncoderFactory(defaultVideoEncoderFactory)
                .setVideoDecoderFactory(defaultVideoDecoderFactory)
                .createPeerConnectionFactory();

        SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", eglBaseContext);
        // create VideoCapturer
        VideoCapturer videoCapturer = createCameraCapturer(true);
        VideoSource videoSource = peerConnectionFactory.createVideoSource(videoCapturer.isScreencast());




        videoCapturer.initialize(surfaceTextureHelper, getApplicationContext(), videoSource.getCapturerObserver());
        videoCapturer.startCapture(480, 640, 30);

       localView = findViewById(R.id.localView);
        localView.setMirror(true);
        localView.init(eglBaseContext, null);

        // create VideoTrack
        VideoTrack videoTrack = peerConnectionFactory.createVideoTrack("100", videoSource);
//        // display in localView
        videoTrack.addSink(localView);


        audioConstraints = new MediaConstraints();
        audioSource = peerConnectionFactory.createAudioSource(audioConstraints);
        localAudioTrack = peerConnectionFactory.createAudioTrack("101", audioSource);
        localAudioTrack.setEnabled(true);



        remoteViews = new SurfaceViewRenderer[]{
                findViewById(R.id.remoteView),
                findViewById(R.id.remoteView2),
                findViewById(R.id.remoteView3),
        };

        for(SurfaceViewRenderer remoteView : remoteViews) {
            remoteView.setMirror(false);
            remoteView.init(eglBaseContext, null);
        }



        mediaStream = peerConnectionFactory.createLocalMediaStream("mediaStream");
        mediaStream.addTrack(videoTrack);
        mediaStream.addTrack(localAudioTrack);
        SignalingClient.get().init(this);


    }
    @Override
    public void CreatePeerConnnect(String str) {
        //子线程创建连接
   /*     new Thread(new Runnable() {
        @Override
        public void run() {
        getOrCreatePeerConnection(str);
        }
       }).start();*/

        getOrCreatePeerConnection(str);
    }
    private synchronized PeerConnection getOrCreatePeerConnection(String socketId) {
//        PeerConnection peerConnection = peerConnectionMap.get(socketId);
//        if(peerConnection != null) {
//            return peerConnection;
//        }
        PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(iceServers, new PeerConnectionAdapter("PC:" + socketId) {
            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                super.onIceCandidate(iceCandidate);
                SignalingClient.get().sendIceCandidate(iceCandidate, socketId);
                Log.d(TAG,"111111");
            }

            @Override
            public void onAddStream(MediaStream mediaStream) {
                super.onAddStream(mediaStream);
                VideoTrack remoteVideoTrack = mediaStream.videoTracks.get(0);
                runOnUiThread(() -> {
                    remoteVideoTrack.addSink(remoteViews[remoteViewsIndex++]);
                    Log.d(TAG,"222222");
                });
            }
        });
        peerConnection.connectionState();
        peerConnection.addStream(mediaStream);
        peerConnectionMap.put(socketId, peerConnection);
        return peerConnection;
    }

    @Override
    public void onCreateRoom() {

    }

    @Override
    public void onPeerJoined(String socketId) {
        PeerConnection peerConnection = peerConnectionMap.get(socketId);
        peerConnection.createOffer(new SdpAdapter("createOfferSdp:" + socketId) {
            @Override
            public void onCreateSuccess(SessionDescription sessionDescription) {
                super.onCreateSuccess(sessionDescription);
                peerConnection.setLocalDescription(new SdpAdapter("setLocalSdp:" + socketId), sessionDescription);
                SignalingClient.get().sendSessionDescription(sessionDescription, socketId);
                Log.d(TAG,"33333");
            }
        }, new MediaConstraints());
    }

    @Override
    public void onSelfJoined() {

    }

    @Override
    public void onPeerLeave(String msg) {

    }
    @Override
    public void onOfferReceived(JSONObject data) {
        runOnUiThread(() -> {
            JSONObject msg = (JSONObject) data;
            JSONObject d = data.optJSONObject("data");
            String socketId = msg.optString("account");
            PeerConnection peerConnection = peerConnectionMap.get(socketId);
           // Log.d("fgfgg111",peerConnectionMap.size()+"");

            Iterator i = peerConnectionMap.entrySet().iterator();
            while (i.hasNext()) {
                Object obj = i.next();
                String key = obj.toString();
                Log.d("fgfgg111",peerConnectionMap.size()+"  key="+key);
            }


            if(peerConnection!=null){
                peerConnection.setRemoteDescription(new SdpAdapter("setRemoteSdp:" + socketId),
                        new SessionDescription(SessionDescription.Type.OFFER, d.optString("sdp")));
                peerConnection.createAnswer(new SdpAdapter("localAnswerSdp") {
                    @Override
                    public void onCreateSuccess(SessionDescription sdp) {
                        super.onCreateSuccess(sdp);
                        peerConnectionMap.get(socketId).setLocalDescription(new SdpAdapter("setLocalSdp:" + socketId), sdp);
                        SignalingClient.get().sendSessionDescription(sdp, socketId);
                        Log.d("reyey222",sdp+"==="+socketId);
                        Log.d(TAG,"444444");
                    }
                }, new MediaConstraints());
            }


//            final String socketId = data.optString("from");
//            PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
//
//
//
//            peerConnection.setRemoteDescription(new SdpAdapter("setRemoteSdp:" + socketId),
//                    new SessionDescription(SessionDescription.Type.OFFER, data.optString("sdp")));
//            peerConnection.createAnswer(new SdpAdapter("localAnswerSdp") {
//                @Override
//                public void onCreateSuccess(SessionDescription sdp) {
//                    super.onCreateSuccess(sdp);
//                    peerConnectionMap.get(socketId).setLocalDescription(new SdpAdapter("setLocalSdp:" + socketId), sdp);
//                    SignalingClient.get().sendSessionDescription(sdp, socketId);
//                    Log.d("reyey222",sdp+"==="+socketId);
//                    Log.d(TAG,"444444");
//                }
//            }, new MediaConstraints());

        });
    }

    @Override
    public void onAnswerReceived(JSONObject data) {
        //子线程Anser
   /*   new Thread(new Runnable() {
      @Override
      public void run() {
          JSONObject msg = (JSONObject) data;
          JSONObject d = data.optJSONObject("data");
          String socketId = msg.optString("account");
          PeerConnection peerConnection = peerConnectionMap.get(socketId);

          Iterator i = peerConnectionMap.entrySet().iterator();
          while (i.hasNext()) {
              Object obj = i.next();
              String key = obj.toString();
              Log.d("fgfgg222",peerConnectionMap.size()+"  key="+key);
          }
          Log.d(TAG,"5555555    "+d.optString("sdp"));
//        String socketId = data.optString("from");
//        PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
          peerConnection.setRemoteDescription(new SdpAdapter(null),
                  new SessionDescription(SessionDescription.Type.ANSWER, d.optString("sdp")));

      }
      }).start();*/
        JSONObject msg = (JSONObject) data;
        JSONObject d = data.optJSONObject("data");
        String socketId = msg.optString("account");

        PeerConnection peerConnection = peerConnectionMap.get(socketId);
          if (peerConnection==null){
            return;
          }
        Iterator i = peerConnectionMap.entrySet().iterator();
        while (i.hasNext()) {
            Object obj = i.next();
            String key = obj.toString();
            Log.d("fgfgg222",peerConnectionMap.size()+"  key="+key);
        }
      //  Log.d(TAG,"5555555    "+d.optString("sdp"));
//        String socketId = data.optString("from");
//        PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
        peerConnection.setRemoteDescription(new SdpAdapter(null),
                new SessionDescription(SessionDescription.Type.ANSWER, d.optString("sdp")));
    }

    @Override
    public void onIceCandidateReceived(JSONObject data) {
//        String socketId = data.optString("from");
//        PeerConnection peerConnection = getOrCreatePeerConnection(socketId);
       Log.d("fdgsgg",data.toString());
        JSONObject msg = (JSONObject) data;
        JSONObject d = data.optJSONObject("data");
        String socketId = msg.optString("account");
        PeerConnection peerConnection = peerConnectionMap.get(socketId);
        if (peerConnection==null){
            return;
        }
        Iterator i = peerConnectionMap.entrySet().iterator();
        while (i.hasNext()) {
            Object obj = i.next();
            String key = obj.toString();
            Log.d("fgfgg3333",peerConnectionMap.size()+"  key="+key);
        }
        if (peerConnection != null){
        peerConnection.addIceCandidate(new IceCandidate(
                d.optString("id"),
                d.optInt("label"),
                d.optString("candidate")
        ));}
        Log.d(TAG,"666666");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        SignalingClient.get().destroy();
    }

    private VideoCapturer createCameraCapturer(boolean isFront) {
        Camera1Enumerator enumerator = new Camera1Enumerator(false);
        final String[] deviceNames = enumerator.getDeviceNames();

        // First, try to find front facing camera
        for (String deviceName : deviceNames) {
            if (isFront ? enumerator.isFrontFacing(deviceName) : enumerator.isBackFacing(deviceName)) {
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);

                if (videoCapturer != null) {
                    return videoCapturer;
                }
            }
        }
        return null;
    }
}